package com.fine.hair.manage.controller;

import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.afterturn.easypoi.excel.entity.TemplateExportParams;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.fine.hair.comm.dto.*;
import com.fine.hair.comm.exception.BusinessException;
import com.fine.hair.comm.model.*;
import com.fine.hair.comm.utils.ApiResponse;
import com.fine.hair.comm.utils.PageInfo;
import com.fine.hair.comm.utils.Utils;
import com.fine.hair.comm.vo.SearchCalendarVO;
import com.fine.hair.manage.mapper.*;
import com.fine.hair.manage.service.UserService;
import com.google.common.collect.Lists;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>用户相关控制层</p>
 *
 * @author mouseyCat
 * @date 2020/10/24 17:30
 */
@RestController
@RequestMapping("/user/")
@Api(tags = {"用户相关接口"})
public class UserController {

    @Autowired
    private Snowflake snowflake;

    @Resource
    private UserMapper userMapper;

    @Autowired
    private UserService userService;

    @Resource
    private EvaluateMapper evaluateMapper;

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private ConsumeMapper consumeMapper;
    @Autowired
    private ServiceTypeChargeMapper serviceTypeChargeMapper;
    @Autowired
    private ServiceTypeMapper serviceTypeMapper;

    @PostMapping("insert-user")
    @ApiOperation("新增用户")
    @Transactional(rollbackFor = Exception.class)
    public ApiResponse insertUser(@RequestBody User user) {
        LambdaQueryWrapper<User> wrapper = Wrappers.lambdaQuery();
        user.setId(snowflake.nextIdStr());
        int count = userService.count(wrapper.eq(User::getPhoneNumber, user.getPhoneNumber()));
        if (count > 0) {
            return ApiResponse.ofFailed("该手机号已存在");
        }
        userService.save(user);
        return ApiResponse.ofSuccess();
    }

    @PostMapping("user-list")
    @ApiOperation("用户列表")
    public ApiResponse<PageInfo<User>> userList(@RequestBody UserListDTO dto) {
        PageInfo<User> userPage = new PageInfo<>(dto.getPageCurr(), dto.getPageSize());
        if (dto.getBirthBySevenDay()) {
            dto.setBirthEndTime(Utils.format(new Date(), "yyyy-MM-dd") + " 00:00:00");
            dto.setBirthStartTime(Utils.format(Utils.beforeDay(new Date(), 7), "yyyy-MM-dd") + " 23:59:59");
        }
        List<User> userList;
        if (StrUtil.isNotBlank(dto.getBranchId())) {
            userList = userMapper.selectUserList(userPage, dto);
        } else {
            userList = userMapper.selectUserListAll(userPage, dto);
        }
        userPage.setRecords(userList);
        return ApiResponse.ofSuccess(userPage);
    }

    @ApiOperation("用户充值记录")
    @PostMapping("charge-list/{userId}")
    public ApiResponse<IPage<Branch>> branchList(@RequestBody BasePage dto, @PathVariable Long userId) {
        PageInfo<ServiceTypeCharge> serviceTypeChargePageInfo = new PageInfo<>(dto.getPageCurr(), dto.getPageSize());
        IPage<ServiceTypeCharge> serviceTypeChargeIPage = serviceTypeChargeMapper.selectPage(serviceTypeChargePageInfo, new LambdaQueryWrapper<ServiceTypeCharge>().eq(ServiceTypeCharge::getUserId, userId));
        List<ServiceTypeCharge> serviceTypeCharges = serviceTypeChargeIPage.getRecords();
        for (ServiceTypeCharge serviceTypeCharge : serviceTypeCharges) {
            serviceTypeCharge.setServiceTypeName(serviceTypeMapper.selectById(serviceTypeCharge.getServiceTypeId()).getServiceName());
        }
        return ApiResponse.ofSuccess(serviceTypeChargeIPage);
    }


    @PostMapping("evaluate-list")
    @ApiOperation("评论列表")
    public ApiResponse<IPage<Evaluate>> evaluateList(@RequestBody EvaluateListDto dto) {
        PageInfo<Evaluate> evaluatePageInfo = new PageInfo<>(dto.getPageCurr(), dto.getPageSize());
        LambdaQueryWrapper<Evaluate> eq = new LambdaQueryWrapper<>();
        if (StrUtil.isNotBlank(dto.getTechnicianId())) {
            eq.eq(Evaluate::getTechnicianId, dto.getTechnicianId());
        }
        return ApiResponse.ofSuccess(evaluateMapper.selectPage(evaluatePageInfo, eq));
    }


    @PostMapping("orderinfo/{userId}")
    @ApiOperation("查询用户订单信息")
    public ApiResponse delEvaluate(@PathVariable Long userId, @RequestBody BasePage dto) {
        PageInfo<Map<String, Object>> pageInfo = new PageInfo<>(dto.getPageCurr(), dto.getPageSize());
        List<Map<String, Object>> list = orderMapper.selectOrderInfoByUserId(userId, pageInfo);
        pageInfo.setRecords(list);
        return ApiResponse.ofSuccess(pageInfo);
    }

    @DeleteMapping("del-evaluate/{evaluateId}")
    @ApiOperation("删除评论")
    public ApiResponse delEvaluate(@PathVariable String evaluateId) {
        evaluateMapper.deleteById(evaluateId);
        return ApiResponse.ofSuccess();
    }

    @ApiOperation("导入用户")
    @PostMapping(value = "importUser")
    public ApiResponse importUser(@RequestParam("file") MultipartFile multipartFile) {
        // 导入用户
        ImportParams params = new ImportParams();
        params.setTitleRows(1);
        params.setHeadRows(1);
        // 将要保存的用户列表信息
        List<ImportUserTemp> result;
        try {
            result = ExcelImportUtil.importExcel(multipartFile.getInputStream(),
                    ImportUserTemp.class, params);
        } catch (Exception e) {
            e.printStackTrace();
            throw new BusinessException("导入时发生了意外，请联系管理员");
        }
        // 删除下面的空数据
        result.removeIf(grantCouponInfo -> grantCouponInfo.getPhoneNumber() == null);
        Boolean isRepeat = importUserTempIsRepeat(result);
        if (isRepeat) {
            throw new BusinessException("用户列表内存在相同手机号，请检查后重新导入");
        }
        List<String> phoneNumberList = result.stream().map(ImportUserTemp::getPhoneNumber).collect(Collectors.toList());
        List<User> users = userMapper.selectList(new LambdaQueryWrapper<User>().in(User::getPhoneNumber,
                phoneNumberList));
        if (users.size() > 0) {
            throw new BusinessException(users.get(0).getPhoneNumber() + "手机号已存在");
        }
        ArrayList<User> pojoList = new ArrayList<>(result.size());
        for (ImportUserTemp r : result) {
            User user = new User();
            user.setBirth(DateUtil.formatDate(r.getBirth()));
            BeanUtil.copyProperties(r, user);
            user.setId(snowflake.nextIdStr());
            user.setNickName(r.getRealName());
            user.setHairStatus(r.getHairStatus());
            // 默认头像
            pojoList.add(user);
        }
        userService.saveBatch(pojoList);

        return ApiResponse.ofSuccess();
    }

    @ApiOperation("获取单个用户的基本信息")
    @GetMapping("base-info/{userId}")
    public ApiResponse<User> userBaseInfo(@PathVariable String userId) {
        User user = userService.getById(userId);
        userService.isNull(user);
        return ApiResponse.ofSuccess(user);
    }

    @ApiOperation("修改单个用户的信息")
    @PostMapping("alter-info")
    @Transactional(rollbackFor = Exception.class)
    public ApiResponse alterInfo(@RequestBody User user) {
        userService.isNull(user);
        Consume consume = new Consume();
        if (Objects.nonNull(user.getHfCount()) && user.getHfCount().intValue() > 0) {
            consume.setSeviceType(1);
            // 同步用户消费
            consume.setConsumeType(1);
            consume.setCount(1);
            consume.setItemId(0L);
            consume.setId(snowflake.nextId());
            consume.setUserId(Long.valueOf(user.getId()));
            consumeMapper.insert(consume);
        }
        if (Objects.nonNull(user.getYfCount()) && user.getYfCount().intValue() > 0) {
            consume.setSeviceType(2);
            // 同步用户消费
            consume.setConsumeType(1);
            consume.setCount(1);
            consume.setItemId(0L);
            consume.setId(snowflake.nextId());
            consume.setUserId(Long.valueOf(user.getId()));
            consumeMapper.insert(consume);
        }
        if (Objects.nonNull(user.getFzCount()) && user.getFzCount().intValue() > 0) {
            consume.setSeviceType(3);
            // 同步用户消费
            consume.setConsumeType(1);
            consume.setCount(1);
            consume.setItemId(0L);
            consume.setId(snowflake.nextId());
            consume.setUserId(Long.valueOf(user.getId()));
            consumeMapper.insert(consume);
        }
        if (Objects.nonNull(user.getDjCount()) && user.getDjCount().intValue() > 0) {
            consume.setSeviceType(4);
            // 同步用户消费
            consume.setConsumeType(1);
            consume.setCount(1);
            consume.setItemId(0L);
            consume.setId(snowflake.nextId());
            consume.setUserId(Long.valueOf(user.getId()));
            consumeMapper.insert(consume);
        }
        if (Objects.nonNull(user.getTbCount()) && user.getTbCount().intValue() > 0) {
            consume.setSeviceType(5);
            // 同步用户消费
            consume.setConsumeType(1);
            consume.setCount(1);
            consume.setItemId(0L);
            consume.setId(snowflake.nextId());
            consume.setUserId(Long.valueOf(user.getId()));
            consumeMapper.insert(consume);
        }
        if (Objects.nonNull(user.getYhCount()) && user.getYhCount().intValue() > 0) {
            consume.setSeviceType(6);
            // 同步用户消费
            consume.setConsumeType(1);
            consume.setCount(1);
            consume.setItemId(0L);
            consume.setId(snowflake.nextId());
            consume.setUserId(Long.valueOf(user.getId()));
            consumeMapper.insert(consume);
        }

        return userService.updateById(user) ? ApiResponse.ofSuccess() : ApiResponse.ofFailed("修改用户信息失败");
    }

    @ApiOperation("查看某个用户某个月的订单日历")
    @PostMapping("user-calendar")
    public ApiResponse userCalendar(@RequestBody UserCalendarDto dto) {
        List<Order> orders = orderMapper.selectAllOrderByDate(dto.getDate());
        ArrayList<SearchCalendarVO> voList = Lists.newArrayList();
        for (Order order : orders) {
            SearchCalendarVO vo = new SearchCalendarVO();
            vo.setYear(order.getExecuteTime().getYear() + 1900);
            vo.setMonth(order.getExecuteTime().getMonth() + 1);
            vo.setDate(order.getExecuteTime().getDay());
            vo.setOrderStatus(Integer.parseInt(order.getOrderStatus()));
            voList.add(vo);
        }
        return ApiResponse.ofSuccess(voList);
    }


    /**
     * 判断List的对象phone是否有重复，有重复true
     *
     * @param orderList
     * @return
     */
    private Boolean importUserTempIsRepeat(List<ImportUserTemp> orderList) {
        Set<ImportUserTemp> set = new TreeSet<>(Comparator.comparing(ImportUserTemp::getPhoneNumber));
        set.addAll(orderList);
        if (set.size() < orderList.size()) {
            return true;
        }
        return false;
    }

    @ApiOperation("下载导入用户模板")
    @GetMapping("downloadTemplate")
    public void downloadTemplate(HttpServletResponse response) throws IOException {
        ClassPathResource classPathResource = new ClassPathResource("template/userImport.xls");
        TemplateExportParams params = new TemplateExportParams(classPathResource.getPath());
        Map<String, Object> map = new HashMap<String, Object>();
        Workbook workbook = ExcelExportUtil.exportExcel(params, map);

        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");
        String fileName = URLEncoder.encode("会员导入模板.xls", "UTF-8");
        response.setHeader("Content-disposition", "attachment;filename=" + fileName);
        OutputStream outputStream = response.getOutputStream();
        workbook.write(outputStream);
        outputStream.close();
    }

}
